//-----------------------------------------------------------------------------
//  Copyright (c) 2013 by HangZhou HenqgQiao Design Corporation. All rights reserved.
//
//  Project  : 
//  Module   : 
//  Parent   : 
//  Children : 
//
//  Description: 
//
//  Parameters:
//  Local Parameters:
//
//  Notes       : 
//
//  Multicycle and False Paths

module AUPP_FFRD(
   input                      GTM_AUPP_RESET,
   input                      GTM_SYS_F8K,
   input                      GTM_SYS_CKOCK,

   input[2:0]                 SPECT_IN_CHNN,
   input                      SPECT_IN_EN,
   input[1:0]                 SPECT_IN_MODE,    // SPE generate control bits, 00--Normal     01--point increase, bytes after H3 not data    10-- point decrease, H3 will be data

   output[2:0]                FSMIN_OUT_FCNT8,
   output[8:0]                FSMIN_OUT_FCNT270,
   output[3:0]                FSMIN_OUT_FCNT9,
   output[1:0]                FSMIN_OUT_PJCNT3,
   output[9:0]                FSMIN_OUT_PJCNT783,
   output                     FSMIN_OUT_HOSPE,
   output[7:0]                FSMIN_OUT_DATA,
   output                     FSMIN_OUT_AIS,
   output                     FSMIN_OUT_J1,
   output[1:0]                FSMIN_OUT_FIFO_STATUS,

   output[2:0]                FFRD_OUT_CHNN,
   output[7:0]                FFRD_OUT_RADDR,
   input[7:0]                 FFRD_IN_DATA,
   input                      FFRD_IN_J1,
   input                      FFRD_IN_AIS,
   input[5:0]                 FFRD_IN_FIFO_BGWADDR
   );

// system timing generate signals
reg[14:0]                     TMG_F8K_RGCNT19440;
reg                           TMG_F8K;
reg[2:0]                      TMG_FCNT8;
reg[8:0]                      TMG_FCNT270;
reg[3:0]                      TMG_FCNT9;
reg[1:0]                      TMG_PSCNT3;
reg[9:0]                      TMG_PSCNT783;
reg[2:0]                      TMG_SPE_CTRL_RCHNN;   // channel number used to read SPE mode control information, forward shift 2 clock
                                                    // cycles make the read out mode information aligned with timing counters.
wire[1:0]                     TMG_SPE_CTRL;

wire                          SPECTRL_RAM_CLKA, SPECTRL_RAM_CLKB;
wire                          SPECTRL_RAM_WEA;
wire[2:0]                     SPECTRL_RAM_ADDRA, SPECTRL_RAM_ADDRB;
wire[1:0]                     SPECTRL_RAM_DINA, SPECTRL_RAM_DOUTB;

reg[2:0]                      SPEG_OUT_FCNT8;
reg[8:0]                      SPEG_OUT_FCNT270;
reg[3:0]                      SPEG_OUT_FCNT9;
reg                           SPEG_OUT_HOSPE;
reg[1:0]                      SPEG_OUT_PSCNT3;
reg[9:0]                      SPEG_OUT_PSCNT783;


wire                          BGADDR_RAM_CLKA, BGADDR_RAM_CLKB;
wire                          BGADDR_RAM_WEA;
wire[2:0]                     BGADDR_RAM_ADDRA, BGADDR_RAM_ADDRB;
wire[5:0]                     BGADDR_RAM_DINA, BGADDR_RAM_DOUTB;
reg[6:0]                      FFR_BGRADDR_RCHNN;
wire[5:0]                     FFR_BGRADDR;
reg[5:0]                      FFR_WR_BGRADDR;

reg[2:0]                      FFR_RDL1_FCNT8, FFR_RDL2_FCNT8;
reg[8:0]                      FFR_RDL1_FCNT270, FFR_RDL2_FCNT270;
reg[3:0]                      FFR_RDL1_FCNT9, FFR_RDL2_FCNT9;
reg                           FFR_RDL1_HOSPE, FFR_RDL2_HOSPE;
reg[1:0]                      FFR_RDL1_PSCNT3, FFR_RDL2_PSCNT3;
reg[9:0]                      FFR_RDL1_PSCNT783, FFR_RDL2_PSCNT783;
reg[5:0]                      FFR_RDL1_BGRADDR, FFR_RDL2_BGRADDR;

reg[2:0]                      FFR_OUT_FCNT8;
reg[8:0]                      FFR_OUT_FCNT270;
reg[3:0]                      FFR_OUT_FCNT9;
reg                           FFR_OUT_HOSPE;
reg[1:0]                      FFR_OUT_PSCNT3;
reg[9:0]                      FFR_OUT_PSCNT783;
reg                           FFR_OUT_AIS;
reg[1:0]                      FFR_OUT_FIFO_STATUS;
reg                           FFR_OUT_J1;
reg[7:0]                      FFR_OUT_DATA;



//********                Section 0 : Timing Generate              ********* //
always @( posedge GTM_SYS_CKOCK or posedge GTM_AUPP_RESET ) begin
   if ( GTM_AUPP_RESET==1'b1 ) begin
      TMG_F8K_RGCNT19440[14:0]                         <= 15'd0;
      TMG_F8K                                          <= 1'b0;
   end
   else begin
      TMG_F8K                                          <= TMG_F8K_RGCNT19440[14:0]==15'd19439;
      if ( GTM_SYS_F8K==1'b1 )
         TMG_F8K_RGCNT19440[14:0]                      <= 15'd12;
      else if ( TMG_F8K_RGCNT19440[14:0]==15'd19439 )
         TMG_F8K_RGCNT19440[14:0]                      <= 15'd0;
      else
         TMG_F8K_RGCNT19440[14:0]                      <= TMG_F8K_RGCNT19440[14:0] +15'd1;
   end
end

always @( posedge GTM_SYS_CKOCK or posedge GTM_AUPP_RESET ) begin
   if (GTM_AUPP_RESET==1'b1)
      TMG_FCNT8[2:0]                                   <= 3'd0;
   else begin
      if ( TMG_F8K==1'b1 )
         TMG_FCNT8[2:0]                                <= 3'd1;
      else
         TMG_FCNT8[2:0]                                <= TMG_FCNT8[2:0] +3'd1;
   end
end
always @( posedge GTM_SYS_CKOCK or posedge GTM_AUPP_RESET ) begin
   if ( GTM_AUPP_RESET==1'b1 )
      TMG_FCNT270[8:0]                                 <= 9'd0;
   else begin
      if ( TMG_F8K==1'b1 )
         TMG_FCNT270[8:0]                              <= 9'd0;
      else begin
         if ( TMG_FCNT8[2:0]==3'd7 ) begin
            if ( TMG_FCNT270[8:0]==9'd269 )
               TMG_FCNT270[8:0]                        <= 9'd0;
            else
               TMG_FCNT270[8:0]                        <= TMG_FCNT270[8:0] +9'd1;
         end
      end
   end
end
always @( posedge GTM_SYS_CKOCK or posedge GTM_AUPP_RESET ) begin
   if ( GTM_AUPP_RESET==1'b1 )
      TMG_FCNT9[3:0]                                   <= 4'd0;
   else begin
      if ( TMG_F8K==1'b1 )
         TMG_FCNT9[3:0]                                <= 4'd0;
      else begin
         if ( TMG_FCNT8[2:0]==3'd7 && TMG_FCNT270[8:0]==9'd269 ) begin
            if ( TMG_FCNT9[3:0]==4'd8 )
               TMG_FCNT9[3:0]                          <= 4'd0;
            else
               TMG_FCNT9[3:0]                          <= TMG_FCNT9[3:0] +4'd1;
         end
      end
   end
end
always @( posedge GTM_SYS_CKOCK or posedge GTM_AUPP_RESET ) begin
   if ( GTM_AUPP_RESET==1'b1 )
      TMG_PSCNT3[1:0]                                  <= 2'd0;
   else begin
      if ( TMG_FCNT8[2:0]==3'd7 && TMG_FCNT270[8:0]==9'd269 && TMG_FCNT9[3:0]==4'd8)
         TMG_PSCNT3[1:0]                               <= 2'd0;
      else if ( TMG_FCNT8[2:0]==3'd7 ) begin
         if ( TMG_PSCNT3[1:0]==2'd2 )
            TMG_PSCNT3[1:0]                            <= 2'd0;
         else
            TMG_PSCNT3[1:0]                            <= TMG_PSCNT3[1:0] +2'd1;
      end
   end
end
always @( posedge GTM_SYS_CKOCK or posedge GTM_AUPP_RESET ) begin
   if ( GTM_AUPP_RESET==1'b1 )
      TMG_PSCNT783[9:0]                                <= 10'd0;
   else begin
      if ( TMG_FCNT8[2:0]==3'd7 && TMG_FCNT270[8:0]==9'd269 && TMG_FCNT9[3:0]==4'd8)
         TMG_PSCNT783[9:0]                             <= 10'd0;
      else if ( TMG_FCNT8[2:0]==3'd7 && TMG_PSCNT3[1:0]==2'd2 && TMG_FCNT270[8:0]>9'd9 ) begin
         if ( TMG_PSCNT783[9:0]==10'd782 )
            TMG_PSCNT783[9:0]                          <= 10'd0;
         else
            TMG_PSCNT783[9:0]                          <= TMG_PSCNT783[9:0] +10'd1;
      end
   end
end


always @( posedge GTM_SYS_CKOCK or posedge GTM_AUPP_RESET ) begin
   if ( GTM_AUPP_RESET==1'b1 )
      TMG_SPE_CTRL_RCHNN[2:0]                          <= 3'd0;
   else begin
      if ( TMG_F8K==1'b1 )
         TMG_SPE_CTRL_RCHNN[2:0]                       <= 3'd3;
      else
         TMG_SPE_CTRL_RCHNN[2:0]                       <= TMG_SPE_CTRL_RCHNN[2:0] +3'd1;
   end
end


  assign SPECTRL_RAM_CLKA         = GTM_SYS_CKOCK;
  assign SPECTRL_RAM_ADDRA[2:0]   = SPECT_IN_CHNN[2:0];
  assign SPECTRL_RAM_WEA          = SPECT_IN_EN;
  assign SPECTRL_RAM_DINA[1:0]    = SPECT_IN_MODE[1:0];

  assign SPECTRL_RAM_CLKB         = GTM_SYS_CKOCK;
  assign SPECTRL_RAM_ADDRB[2:0]   = TMG_SPE_CTRL_RCHNN[2:0];
  assign TMG_SPE_CTRL[1:0]        = SPECTRL_RAM_DOUTB[1:0];
AURG_SPEBD_RAM16_2_2              INST_SPECTRL_RAM16_2_2(
   .CLKA                          ( SPECTRL_RAM_CLKA ),
   .WEA                           ( SPECTRL_RAM_WEA ),
   .ADDRA                         ( SPECTRL_RAM_ADDRA[2:0] ),
   .DINA                          ( SPECTRL_RAM_DINA[1:0] ),

   .CLKB                          ( SPECTRL_RAM_CLKB ),
   .ADDRB                         ( SPECTRL_RAM_ADDRB[2:0] ),
   .DOUTB                         ( SPECTRL_RAM_DOUTB[1:0] )
   );


// output SPE generate
always @( posedge GTM_SYS_CKOCK or posedge GTM_AUPP_RESET ) begin
   if ( GTM_AUPP_RESET==1'b1 ) begin
      SPEG_OUT_FCNT8[2:0]                           <= 3'd0;
      SPEG_OUT_FCNT270[8:0]                         <= 9'd0;
      SPEG_OUT_FCNT9[3:0]                           <= 4'd0;
      SPEG_OUT_HOSPE                                <= 1'd0;
      SPEG_OUT_PSCNT3[1:0]                          <= 2'd0;
      SPEG_OUT_PSCNT783[9:0]                        <= 10'd0;
   end
   else begin
      SPEG_OUT_FCNT8[2:0]                           <= TMG_FCNT8[2:0];
      SPEG_OUT_FCNT270[8:0]                         <= TMG_FCNT270[8:0];
      SPEG_OUT_FCNT9[3:0]                           <= TMG_FCNT9[3:0];
      SPEG_OUT_PSCNT3[1:0]                          <= TMG_PSCNT3[1:0];
      SPEG_OUT_PSCNT783[9:0]                        <= TMG_PSCNT783[9:0];
      if ( TMG_SPE_CTRL[1:0]==2'd0) begin        // normal SPE
         SPEG_OUT_HOSPE                             <= ( TMG_FCNT270[8:0]>=9'd9 );
      end
      else if ( TMG_SPE_CTRL[1:0]==2'd1) begin   // increase SPE                   
         if ( TMG_FCNT9[3:0]==4'd3 )
            SPEG_OUT_HOSPE                          <= (TMG_FCNT270[8:0]>=9'd12 );
         else
            SPEG_OUT_HOSPE                          <= (TMG_FCNT270[8:0]>=9'd9 );
      end
      else if ( TMG_SPE_CTRL[1:0]==2'd2) begin   // decrease SPE
         if ( TMG_FCNT9[3:0]==4'd3 )
            SPEG_OUT_HOSPE                          <= (TMG_FCNT270[8:0]>=9'd6 );
         else
            SPEG_OUT_HOSPE                          <= (TMG_FCNT270[8:0]>=9'd9 );
      end
   end
end



//********                  Section 1 : FIFO Read control                ********* //
always @( posedge GTM_SYS_CKOCK or posedge GTM_AUPP_RESET ) begin
   if ( GTM_AUPP_RESET==1'b1 )
      FFR_BGRADDR_RCHNN[2:0]                         <= 3'd0;
   else begin
      if ( SPEG_OUT_FCNT8[2:0]==3'd0 )
         FFR_BGRADDR_RCHNN[2:0]                      <= 3'd3;
      else
         FFR_BGRADDR_RCHNN[2:0]                      <= FFR_BGRADDR_RCHNN[2:0] +3'd1;
   end
end


  assign BGADDR_RAM_CLKA          = GTM_SYS_CKOCK;
  assign BGADDR_RAM_WEA           = SPEG_OUT_HOSPE;
  assign BGADDR_RAM_ADDRA[2:0]    = SPEG_OUT_FCNT8[2:0];
  assign BGADDR_RAM_DINA[5:0]     = FFR_WR_BGRADDR[5:0];

  assign BGADDR_RAM_CLKB          = GTM_SYS_CKOCK;
  assign BGADDR_RAM_ADDRB[2:0]    = FFR_BGRADDR_RCHNN[2:0];
  assign FFR_BGRADDR[5:0]          = BGADDR_RAM_DOUTB[5:0];

AURG_FFRD_RAM48_6_6               INST_BGADDR_RAM48_6_6(
   .CLKA                          ( BGADDR_RAM_CLKA ),
   .WEA                           ( BGADDR_RAM_WEA ),
   .ADDRA                         ( BGADDR_RAM_ADDRA[2:0] ),
   .DINA                          ( BGADDR_RAM_DINA[5:0] ),

   .CLKB                          ( BGADDR_RAM_CLKB ),
   .ADDRB                         ( BGADDR_RAM_ADDRB[2:0] ),
   .DOUTB                         ( BGADDR_RAM_DOUTB[5:0] )
   );

always @( SPEG_OUT_HOSPE or SPEG_OUT_PSCNT3 or FFR_BGRADDR) begin
   if ( SPEG_OUT_HOSPE==1'b1 && SPEG_OUT_PSCNT3[1:0]==2'd2 )
      FFR_WR_BGRADDR[5:0]                             <= FFR_BGRADDR[5:0] +6'd1;
   else
      FFR_WR_BGRADDR[5:0]                             <= FFR_BGRADDR[5:0];
end

  assign FFRD_OUT_CHNN[2:0]          = SPEG_OUT_FCNT8[2:0];
  assign FFRD_OUT_RADDR[7:0]         = {FFR_BGRADDR[5:0], SPEG_OUT_PSCNT3[1:0] };

always @( posedge GTM_SYS_CKOCK or posedge GTM_AUPP_RESET ) begin
   if ( GTM_AUPP_RESET==1'b1 ) begin
      FFR_RDL1_FCNT8[2:0]                            <= 3'd0;
      FFR_RDL1_FCNT270[8:0]                          <= 9'd0;
      FFR_RDL1_FCNT9[3:0]                            <= 4'd0;
      FFR_RDL1_HOSPE                                 <= 1'd0;
      FFR_RDL1_PSCNT3[1:0]                           <= 2'd0;
      FFR_RDL1_PSCNT783[9:0]                         <= 10'd0;
      FFR_RDL1_BGRADDR[5:0]                          <= 6'd0;
      FFR_RDL2_FCNT8[2:0]                            <= 3'd0;
      FFR_RDL2_FCNT270[8:0]                          <= 9'd0;
      FFR_RDL2_FCNT9[3:0]                            <= 4'd0;
      FFR_RDL2_HOSPE                                 <= 1'd0;
      FFR_RDL2_PSCNT3[1:0]                           <= 2'd0;
      FFR_RDL2_PSCNT783[9:0]                         <= 10'd0;
      FFR_RDL2_BGRADDR[5:0]                          <= 6'd0;
   end
   else begin
      FFR_RDL1_FCNT8[2:0]                            <= SPEG_OUT_FCNT8[2:0];
      FFR_RDL1_FCNT270[8:0]                          <= SPEG_OUT_FCNT270[8:0];
      FFR_RDL1_FCNT9[3:0]                            <= SPEG_OUT_FCNT9[3:0];
      FFR_RDL1_HOSPE                                 <= SPEG_OUT_HOSPE;
      FFR_RDL1_PSCNT3[1:0]                           <= SPEG_OUT_PSCNT3[1:0];
      FFR_RDL1_PSCNT783[9:0]                         <= SPEG_OUT_PSCNT783[9:0];
      FFR_RDL1_BGRADDR[5:0]                          <= FFR_BGRADDR[5:0];
      FFR_RDL2_FCNT8[2:0]                            <= FFR_RDL1_FCNT8[2:0];
      FFR_RDL2_FCNT270[8:0]                          <= FFR_RDL1_FCNT270[8:0];
      FFR_RDL2_FCNT9[3:0]                            <= FFR_RDL1_FCNT9[3:0];
      FFR_RDL2_HOSPE                                 <= FFR_RDL1_HOSPE;
      FFR_RDL2_PSCNT3[1:0]                           <= FFR_RDL1_PSCNT3[1:0];
      FFR_RDL2_PSCNT783[9:0]                         <= FFR_RDL1_PSCNT783[9:0];
      FFR_RDL2_BGRADDR[5:0]                          <= FFR_RDL1_BGRADDR;
   end
end

always @( posedge GTM_SYS_CKOCK or posedge GTM_AUPP_RESET ) begin
   if ( GTM_AUPP_RESET==1'b1 ) begin
      FFR_OUT_FCNT8[2:0]                             <= 3'd0;
      FFR_OUT_FCNT270[8:0]                           <= 9'd0;
      FFR_OUT_FCNT9[3:0]                             <= 4'd0;
      FFR_OUT_HOSPE                                  <= 1'd0;
      FFR_OUT_PSCNT3[1:0]                            <= 2'd0;
      FFR_OUT_PSCNT783[9:0]                          <= 10'd0;
      FFR_OUT_AIS                                    <= 1'd0;
      FFR_OUT_J1                                     <= 1'b0;
      FFR_OUT_DATA[7:0]                              <= 8'd0;
      FFR_OUT_FIFO_STATUS[1:0]                       <= 2'd0;
   end
   else begin
      FFR_OUT_FCNT8[2:0]                             <= FFR_RDL2_FCNT8[2:0];
      FFR_OUT_FCNT270[8:0]                           <= FFR_RDL2_FCNT270[8:0];
      FFR_OUT_FCNT9[3:0]                             <= FFR_RDL2_FCNT9[3:0];
      FFR_OUT_HOSPE                                  <= FFR_RDL2_HOSPE;
      FFR_OUT_PSCNT3[1:0]                            <= FFR_RDL2_PSCNT3[1:0];
      FFR_OUT_PSCNT783[9:0]                          <= FFR_RDL2_PSCNT783[9:0];
      FFR_OUT_AIS                                    <= FFRD_IN_AIS;
      FFR_OUT_J1                                     <= FFRD_IN_J1;
      FFR_OUT_DATA[7:0]                              <= FFRD_IN_DATA[7:0];
      if ( FFRD_IN_FIFO_BGWADDR[5:0]-FFR_RDL2_BGRADDR[5:0]>6'd60 || FFRD_IN_FIFO_BGWADDR[5:0]-FFR_RDL2_BGRADDR[5:0]<6'd4)
          FFR_OUT_FIFO_STATUS[1:0]                   <= 2'd3;
      else if ( FFRD_IN_FIFO_BGWADDR[5:0]-FFR_RDL2_BGRADDR[5:0]<6'd14 )
          FFR_OUT_FIFO_STATUS[1:0]                   <= 2'd0;
      else if ( FFRD_IN_FIFO_BGWADDR[5:0]-FFR_RDL2_BGRADDR[5:0]>6'd50 )
          FFR_OUT_FIFO_STATUS[1:0]                   <= 2'd2;
      else
          FFR_OUT_FIFO_STATUS[1:0]                   <= 2'd1;
   end
end

  assign FSMIN_OUT_FCNT8[2:0]       = FFR_OUT_FCNT8[2:0];
  assign FSMIN_OUT_FCNT270[8:0]     = FFR_OUT_FCNT270[8:0];
  assign FSMIN_OUT_FCNT9[3:0]       = FFR_OUT_FCNT9[3:0];
  assign FSMIN_OUT_PJCNT3[1:0]      = FFR_OUT_PSCNT3[1:0];
  assign FSMIN_OUT_PJCNT783[9:0]    = FFR_OUT_PSCNT783[9:0];
  assign FSMIN_OUT_HOSPE            = FFR_OUT_HOSPE;
  assign FSMIN_OUT_DATA[7:0]        = FFR_OUT_DATA[7:0];
  assign FSMIN_OUT_AIS              = FFR_OUT_AIS;
  assign FSMIN_OUT_J1               = FFR_OUT_J1;
  assign FSMIN_OUT_FIFO_STATUS[1:0] = FFR_OUT_FIFO_STATUS[1:0];

endmodule
